package com.leyou.service;

import com.leyou.constant.Constants;
import com.leyou.constant.MQConstants;
import com.leyou.exception.LyException;
import com.leyou.exception.domain.ExceptionEnum;
import com.leyou.utils.BeanHelper;
import com.leyou.UserDTO;
import com.leyou.mapper.UserMapper;
import com.leyou.pojo.User;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

@Service
@Transactional
public class UserService {

    @Autowired
    UserMapper mapper;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private BCryptPasswordEncoder encoder;

    /**
     * 校验用户名或者手机是否唯一
     *
     * @param data
     * @param type
     * @return
     */
    public Boolean checkUserNameOrPhone(String data, Integer type) {
        if (StringUtils.isBlank(data) || type == null) {
            throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
        }
        try {
            User user = new User();
            switch (type) {
                case 1:
                    user.setUsername(data);
                    break;
                case 2:
                    user.setPhone(data);
                    break;
            }
            int count = mapper.selectCount(user);
            return count == 0;
        } catch (Exception e) {
            e.printStackTrace();
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
    }

    /**
     * 获得验证码
     * 1.生成验证码
     * 2.存入redis
     * 3.使用消息队列发送短信
     *
     * @param phone 手机号码
     */
    public void getCheckCode(String phone) {
        try {
            String code = RandomStringUtils.randomNumeric(6);
            redisTemplate.opsForValue().set(Constants.CHECK_CODE_PRE + phone, code);
            Map<String, String> map = new HashMap<>();
            map.put("phone", phone);
            map.put("code", code);
            amqpTemplate.convertAndSend(MQConstants.Exchange.SMS_EXCHANGE_NAME, MQConstants.RoutingKey.VERIFY_CODE_KEY, map);
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
        }
    }

    /**
     * 注册
     * 1.验证验证码是否相等
     * 2.密码加盐加蜜
     * 3.user表插入一条记录
     */

    public void register(User user, String code) {
        if (user == null || StringUtils.isBlank(code)) {
            throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
        }
        String redisCode = redisTemplate.opsForValue().get(Constants.CHECK_CODE_PRE + user.getPhone());
        if (!StringUtils.equals(redisCode, code)) {
            throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
        }
        try {
            String password = user.getPassword();
            String encode = encoder.encode(password);
            user.setPassword(encode);
            mapper.insertSelective(user);
        } catch (Exception e) {
            e.printStackTrace();
            throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
        }
    }

    /**
     * @param username
     * @param password 通过用户名和密码返回userdto
     */
    public UserDTO findUserNameAndPassword(String username, String password) {
        User record = new User();
        record.setUsername(username);
        User user = mapper.selectOne(record);
        if (user == null) {
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        String pwd = user.getPassword();
        boolean matches = encoder.matches(password, pwd);
        if (matches) {
            return BeanHelper.copyProperties(user, UserDTO.class);
        }
        throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
    }
}
